import { ipairs, pairs } from "@/utils/lua"
import { table } from "@/utils/lua/table"
import { BattleData } from "../extra/battleData"
import { FightPlayer } from "./Fightplayer"
import emitter from "@/utils/events"
import Basic from "@/global"
import { skillTable } from "../data/SkillTable"
import { Character, CharacterData } from "./Character"

export class Battle {
  game_id: number
  battletype: number
  enter?: boolean
  winner: FightPlayer | null = null
  giveuper: string
  rnd: number
  actnum: number
  playerSide: 'A' | 'B'
  /** 初始ID */
  derivativeID: number
  characters: Record<string, Character | undefined>
  competes = []
  playerA: FightPlayer
  playerB: FightPlayer
  derivatives: Record<string, Character | null> = {

  }
  video: any
  gamer: FightPlayer
  view: boolean = false

  constructor(game_id: number, para: BattleData) {
    // 记录游戏ID
    this.game_id = game_id
    this.battletype = para.battletype
    this.enter = para.enter

    // 战场基本信息
    this.winner = null
    this.giveuper = ""


    this.rnd = para.rnd || 0
    this.actnum = para.actnum || 0
    this.playerSide = para.playerSide || "A"

    // 初始ID
    this.derivativeID = para.derivativeID || 0
    this.derivatives = {

    }

    // 设定随机函数 TODO:

    // 创建队伍
    this.characters = {}
    // this.fieldcards = []
    this.competes = []
    this.playerA = new FightPlayer(para.playerA, this)
    this.playerB = new FightPlayer(para.playerB, this)
    this.playerA.side = "A"
    this.playerB.side = "B"
    this.playerA.opponent = this.playerB
    this.playerB.opponent = this.playerA
    this.video = para.video
    this.gamer = (this.playerSide == "A") ? this.playerA : this.playerB
  }

  createCharacter(player: FightPlayer, creator: Character | undefined, card: CharacterData) {
    const fightcard = new Character(card.id, card, this)
    this.characters[fightcard.id] = fightcard
    fightcard.player = player
    fightcard.creator = creator
    player.fields.push(fightcard)
    return fightcard
  }
  start() {
  }
  getPlayer(side: 'A' | 'B') {
    return (side == "A") ? this.playerA : this.playerB
  }
  async refreshAuras() {
    for (let i in this.characters) {
      let card = this.characters[i]
      if (!card) continue
      card.refreshAuras()
      card.dirty = true
    }
    await emitter.emitSerial('afterRefreshAuras')
  }
  round() {
    // TODO
    this.rnd = this.rnd + 1
    // this.performer = nil
    // this.audioed = nil
  }
  // 得到衍生物
  getDerivative(id?: string) {
    if (!id) return
    return this.characters[id]
  }
  async activateEffects(timing, para) {
    let cards = table.copy(this.characters);
    let fieldcards = table.copy(this.fieldcards);
    for (const [_, fightcard] of pairs(fieldcards)) {
      if (!fightcard) continue
      await fightcard.activateEffects(timing, para);
      await fightcard.activateCounter(timing, para);
      cards[fightcard.id] = undefined;
    }
    for (const [_, fightcard] of pairs(cards)) {
      if (!fightcard) continue
      await fightcard.activateEffects(timing, para);
      await fightcard.activateCounter(timing, para);
    }
    await this.activateDeaths();
  }
  async activateDeaths() {
    let fieldcards = table.copy(this.fieldcards);
    for (const [_, fightcard] of ipairs(fieldcards)) {
      if (!fightcard) continue
      let field = undefined;
      field = fightcard.player.getPos(fightcard)[1]

      if (!fightcard.dead && (fightcard.temppro.currentHP <= 0 || fightcard.temppro.doomed)) {
        const { deathrattle } = fightcard.temppro
        fightcard.dead = true
        await emitter.emitSerial('timing', ['beforedie', '', { obj: fightcard, para: { field } }])
        if (deathrattle?.length) {
          for (let item of (deathrattle || [])) {
            let skill = Basic.skill[item]
            await skillTable[item]?.func.call({ battle: this, fightcard: fightcard, skill }, undefined, field)
          }
        }
        await emitter.emitSerial('timing', ['afterdie', '', { obj: fightcard, para: { field } }])
      }
    }
  }
  get fieldcards() {
    const cards = Object.values(this.characters).filter(item => !item.dead)
    return cards
  }
}